package team.seekers.oj.course.service;

import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import team.seekers.oj.auth.enums.PermissionEnum;
import team.seekers.oj.common.entity.PageResult;
import team.seekers.oj.common.entity.UserSessionDTO;
import team.seekers.oj.common.enums.ApiExceptionEnum;
import team.seekers.oj.common.exception.ApiException;
import team.seekers.oj.common.util.AssertUtils;
import team.seekers.oj.course.client.GroupClient;
import team.seekers.oj.course.client.UserClient;
import team.seekers.oj.course.conventer.CourseConvertUtils;
import team.seekers.oj.course.conventer.CourseListConverter;
import team.seekers.oj.course.dao.CourseDao;
import team.seekers.oj.course.dao.CourseListDao;
import team.seekers.oj.course.dto.CourseListDTO;
import team.seekers.oj.course.dto.CourseListReqDTO;
import team.seekers.oj.course.dto.CourseManageDTO;
import team.seekers.oj.course.entity.CourseDO;
import team.seekers.oj.course.entity.CourseListDO;
import team.seekers.oj.course.entity.CourseLiveDO;
import team.seekers.oj.course.entity.vo.CourseInfoVO;
import team.seekers.oj.lesson.dto.ChapterListDTO;
import team.seekers.oj.third.controller.LiveController;

import java.io.IOException;
import java.util.List;


@Service
public class CourseService {

    @Autowired
    private CourseDao courseDao;

    @Autowired
    private CourseManageService courseManageService;

    @Autowired
    private CourseListDao courseListDao;

    @Autowired
    private CourseListConverter courseListConverter;


    @Autowired
    private UserClient userClient;

    @Autowired
    private GroupClient groupClient;

    public List<ChapterListDTO> queryIdToChaptersSections(Long courseId) throws IOException, ClassNotFoundException {
        CourseDO courseDO = courseDao.lambdaQuery().select(
                CourseDO::getId,
                CourseDO::getVersion,
                CourseDO::getChaptersSections
        ).eq(CourseDO::getId, courseId).one();
        AssertUtils.notNull(courseDO, ApiExceptionEnum.GROUP_NOT_FOUND);
        return CourseConvertUtils.chaptersSectionsToChapterList(courseDO.getChaptersSections());
    }

    public PageResult<CourseListDTO> page(CourseListReqDTO reqDTO) {
        LambdaQueryChainWrapper<CourseListDO> query = courseListDao.lambdaQuery()
                .orderByDesc(CourseListDO::getGmtModified);
        if(reqDTO.getStudentId() != null){
            List<Long> groups = userClient.queryParticipateGroup(reqDTO.getStudentId());
            query.and(
                    course -> {
                        for (Long groupId : groups) {
                            List<Long> courses = groupClient.queryParticipateCourse(groupId);
                            for (Long courseId : courses) {
                                course.or().eq(CourseListDO::getId, courseId);
                            }
                        }
                        course.or().eq(CourseListDO::getId, null);
                    }
            );
        }else if(reqDTO.getTeacherId() != null){
            query.eq(CourseListDO::getUserId,reqDTO.getTeacherId());
        }
        Page<CourseListDO> pageResult = query.page(new Page<>(reqDTO.getPageNow(), reqDTO.getPageSize()));
        List<CourseListDTO> courseListDTOS = courseListConverter.to(pageResult.getRecords());
        for (CourseListDTO courseListDTO : courseListDTOS) {
            String teacher = userClient.userIdToUsername(courseListDTO.getUserId());
            courseListDTO.setTeacher(teacher);
        }
        return new PageResult<>(pageResult.getPages(), courseListDTOS);
    }

    public boolean isCourseManager(Long groupCreatorId, UserSessionDTO userSessionDTO) {
        return PermissionEnum.SUPERADMIN.in(userSessionDTO) ||
                userSessionDTO.userIdEquals(groupCreatorId);
    }

    public void join(long courseId, Long groupId) {
        CourseManageDTO query = courseManageService.query(courseId);
        query.getParticipants().add(groupId);
        query.setParticipantNum(query.getParticipantNum()+1);
        courseManageService.update(query);
    }

    public void out(long courseId, Long groupId) {
        CourseManageDTO query = courseManageService.query(courseId);
        boolean remove = query.getParticipants().remove(groupId);
        if(!remove){
            throw new ApiException(ApiExceptionEnum.GROUP_NOT_IN);
        }
        query.setParticipantNum(query.getParticipantNum()-1);
        courseManageService.update(query);
    }

    public CourseInfoVO getInfo(long courseId) {
        CourseDO byId = courseDao.getById(courseId);
        CourseInfoVO courseInfoVO = new CourseInfoVO();
        courseInfoVO.setId(byId.getId());
        courseInfoVO.setName(byId.getName());
        courseInfoVO.setStatus(byId.getStatus());
        courseInfoVO.setCover(byId.getCover());
        return courseInfoVO;
    }
}
